using System;
using System.Xml.Serialization;

namespace SharpMud.MudLib.SAMPLE.Environment
{
	
	/// <summary>
	/// A stand-alone room identification type. Just wraps a number up as a loose reference
	/// to a room.
	/// </summary>
	[XmlRoot("RoomID")]
	public class RoomID : IDisposable
	{
		#region Private Variables
		private System.Int32 _SerialNumber;
		private Room		 _Room;
		#endregion

		#region Constructors
		/// <summary>
		/// Creates a new, empty RoomID
		/// </summary>
		public RoomID()
		{
			this._SerialNumber = 0;
			this._Room =null;
		}
		public RoomID(string s)
		{
			this._SerialNumber = System.Int32.Parse(s,System.Globalization.NumberStyles.HexNumber);
			this._Room = null;
		}
		public RoomID(RoomID r)
			:this(r,false)
		{
		}
		public RoomID(RoomID r,bool trackChanges)
		{
			this._SerialNumber = r._SerialNumber;
			this._Room = r._Room;
			if(trackChanges)
			{
				r.ValueChanged+=new RoomIDChangedHandler(Source_ValueChanged);
			}
		}
		public RoomID(System.Int32 serialNumber)
			:this(serialNumber,null)
		{
		}
		public RoomID(System.Int32 serialNumber, Room room)
		{
			this._SerialNumber = serialNumber;
			this._Room = room;
		}
		public RoomID(Room r)
			:this(r,false)
		{
		}
		public RoomID(Room r,bool trackChanges)
		{
			this._SerialNumber = r.RoomID._SerialNumber;
			this._Room = r;
			if(trackChanges)
			{
				r.RoomID.ValueChanged+=new RoomIDChangedHandler(Source_ValueChanged);
			}
		}
		#endregion

		/// <summary>
		/// Gets or sets this room ID's expression as a string
		/// </summary>
		[XmlText()]
		public string StringValue
		{
			get
			{
				return this.ToString();
			}
			set
			{
				if(value.Trim().ToLower()!=StringValue.Trim().ToLower())
				{
					this._SerialNumber = System.Int32.Parse(value,System.Globalization.NumberStyles.HexNumber);
                    if(ValueChanged!=null) ValueChanged(this);					
				}
			}
		}

		/// <summary>
		/// The reference to the room that this RoomID points to, if the room is loaded and such
		/// </summary>
		[XmlIgnore()]
		public Room Room
		{
			get
			{
				return this._Room;
			}
			set
			{
				if(value.RoomID.Equals(this))
				{
					this._Room = value;
				}
				else
					throw new InvalidOperationException();
			}
		}

		/// <summary>
		/// Represents an empty/null RoomID
		/// </summary>
		public static RoomID Empty
		{
			get
			{
				return new RoomID();
			}
		}
		
		public event RoomIDChangedHandler ValueChanged;

		/// <summary>
		/// Gets or sets the numerical value of a string
		/// </summary>
		[XmlIgnore()]
		public System.Int32 Value
		{
			get
			{
				return this._SerialNumber;
			}
			set
			{
				if(value!=this._SerialNumber)
				{
					this._SerialNumber = value;
					if(ValueChanged!=null) ValueChanged(this);
				}
			}
		}

		#region ToString and FromString
		public static RoomID FromString(string s)
		{
			return new RoomID(s);
		}

		public override string ToString()
		{
			return Microsoft.VisualBasic.Conversion.Hex(this._SerialNumber);
		}
		#endregion

		#region Private Event Handlers
		private void Source_ValueChanged(RoomID sender)
		{
			this._SerialNumber = sender._SerialNumber;
		}
		#endregion

		#region IDisposable Members

		public void Dispose()
		{
		}

		#endregion

		public override bool Equals(object obj)
		{
			if(obj==null)
			{
				return false;
			}
			if(obj.GetType()==typeof(RoomID))
			{
				return Equals((RoomID)obj);
			}
			else
			{
				return base.Equals(obj);
			}
		}

		public override int GetHashCode()
		{
			return this.Value;
		}

		
		public bool Equals(RoomID obj)
		{
			if((object)obj==null) return false;
			return (obj.Value==this.Value);
		}

		public static bool operator==(RoomID obj1, RoomID obj2)
		{
			if((object)obj1==null && (object)obj2!=null)
				return false;
			if((object)obj1!=null && (object)obj2==null)
				return false;
			if((object)obj1==null && (object)obj2==null)
				return true;

			return obj1.Equals(obj2);
		}

		public static bool operator!=(RoomID obj1, RoomID obj2)
		{
			return !(obj1==obj2);
		}
	}
}
